package com.chenyuxin.ilp.service.file.Impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.chenyuxin.ilp.exception.BaseException;
import com.chenyuxin.ilp.mapper.file.FileFolderMapper;
import com.chenyuxin.ilp.mapper.file.FileMetaMapper;
import com.chenyuxin.ilp.mapper.file.FilePreviewMapper;
import com.chenyuxin.ilp.mapper.user.UserStorageMapper;
import com.chenyuxin.ilp.model.constant.FileExtensionConstant;
import com.chenyuxin.ilp.model.constant.FileSuccessConstant;
import com.chenyuxin.ilp.model.dto.file.DeleteFileDto;
import com.chenyuxin.ilp.model.entity.file.FileFolder;
import com.chenyuxin.ilp.model.entity.file.FileMeta;
import com.chenyuxin.ilp.model.entity.file.FilePreview;
import com.chenyuxin.ilp.model.entity.user.UserStorage;
import com.chenyuxin.ilp.model.enums.exception.ExceptionEnums;
import com.chenyuxin.ilp.model.enums.exception.FileExceptionEnums;
import com.chenyuxin.ilp.model.pojo.Result;
import com.chenyuxin.ilp.model.vo.file.RecycleFileVo;
import com.chenyuxin.ilp.service.file.RecycleBinService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Slf4j
@Service
public class RecycleBinServiceImpl implements RecycleBinService {
    @Value("${minio.bucket.files}")
    private String bucket;
    @Autowired
    private FileMetaMapper fileMetaMapper;
    @Autowired
    private UserStorageMapper userStorageMapper;
    @Autowired
    private MinioServiceImpl minioService;
    @Autowired
    private FileFolderMapper fileFolderMapper;
    @Autowired
    private FilePreviewMapper filePreviewMapper;
    // 查询回收站文件
    @Override
    public Result selectRecycleFile(String userId) {
        LambdaQueryWrapper<FileMeta> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FileMeta::getUserId,userId)
                .eq(FileMeta::getIsDelete,1);
        List<FileMeta> fileMetas = fileMetaMapper.selectList(wrapper);
        List<RecycleFileVo> recycleFileVos = new ArrayList<>();
        for (FileMeta fileMeta:fileMetas){
            RecycleFileVo recycleFileVo = BeanUtil.copyProperties(fileMeta, RecycleFileVo.class);
            recycleFileVo.setType(1);
            recycleFileVos.add(recycleFileVo);
        }
        return Result.ok(FileSuccessConstant.SELECT_RECYCLE_SUCCESS,recycleFileVos);
    }
    // 删除回收站文件
    @Transactional
    @Override
    public Result deleteRecycleFile(String userId, Long fileId) {
        // 查询文件信息
        FileMeta fileMeta = fileMetaMapper.selectById(fileId);
        if(fileMeta==null){
            throw new BaseException(FileExceptionEnums.FILE_NOT_EXIST);
        }
        String fileName = fileMeta.getFileName();
        String extension = fileName.substring(fileName.lastIndexOf("."));
        // 删除文件表信息
        LambdaQueryWrapper<FileMeta> fileWrapper = new LambdaQueryWrapper<>();
        fileWrapper.eq(FileMeta::getId,fileId)
                .eq(FileMeta::getUserId,userId)
                .eq(FileMeta::getIsDelete,1);
        int delete = fileMetaMapper.delete(fileWrapper);
        if(delete!=1){
            throw new BaseException(ExceptionEnums.SYSTEM_ERROR);
        }
        // 修改存储表信息
        LambdaUpdateWrapper<UserStorage> storageWrapper = new LambdaUpdateWrapper<>();
        storageWrapper.eq(UserStorage::getId,userId)
                .setSql("used_size = used_size - " + fileMeta.getFileSize());
        userStorageMapper.update(storageWrapper);
        // 删除minio文件
        String objectName = "/"+userId+"/file/"+fileId+extension;
        Boolean minioDelete = minioService.delete(bucket, objectName);
        if(!minioDelete){
            log.error("删除minio文件失败,objectName:{}",objectName);
            throw new BaseException(ExceptionEnums.SYSTEM_ERROR);
        }
        if(FileExtensionConstant.convertPreview.contains(extension)){
            // 删除预览信息
            LambdaQueryWrapper<FilePreview> previewWrapper = new LambdaQueryWrapper<>();
            previewWrapper.eq(FilePreview::getInitialFileId,fileId);
            List<FilePreview> filePreviews = filePreviewMapper.selectList(previewWrapper);
            for (FilePreview filePreview:filePreviews){
                objectName = "/"+userId+"/preview/"+filePreview.getPreviewFileName();
                minioService.delete(bucket,objectName);
                filePreviewMapper.deleteById(filePreview.getId());
            }
        }
        return Result.ok(FileSuccessConstant.DELETE_RECYCLE_FILE_SUCCESS,null);
    }
    // 找回回收站文件
    @Transactional
    @Override
    public Result retrievalRecycleFile(String fileId, String userId) {
        //1 获取用户根文件夹
        LambdaQueryWrapper<FileFolder> folderWrapper = new LambdaQueryWrapper<>();
        folderWrapper.eq(FileFolder::getUserId,userId)
                .eq(FileFolder::getLevel,0);
        FileFolder fileFolder = fileFolderMapper.selectOne(folderWrapper);
        if(fileFolder==null){
            log.error("用户根路径不存在,userId:"+userId);
            throw new BaseException(ExceptionEnums.SYSTEM_ERROR);
        }
        //2 获取文件信息
        LambdaQueryWrapper<FileMeta> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FileMeta::getId,fileId)
                .eq(FileMeta::getUserId,userId);
        FileMeta fileMeta = fileMetaMapper.selectOne(wrapper);
        if (fileMeta==null){
            throw new BaseException(FileExceptionEnums.FILE_NOT_EXIST);
        }
        //3 判断用户根路径下有没有同名文件
        LambdaQueryWrapper<FileMeta> rootWrapper = new LambdaQueryWrapper<>();
        rootWrapper.eq(FileMeta::getParentId,fileFolder.getId())
                .eq(FileMeta::getFileName,fileMeta.getFileName())
                .eq(FileMeta::getUserId,fileMeta.getUserId())
                .eq(FileMeta::getIsDelete,0);
        FileMeta sameName = fileMetaMapper.selectOne(rootWrapper);
        if(sameName!=null){
            throw new BaseException(FileExceptionEnums.SAME_NAME_IN_ROOT);
        }
        //3 修改数据库文件路径
        LambdaUpdateWrapper<FileMeta> fileUpdateWrapper = new LambdaUpdateWrapper<>();
        fileUpdateWrapper.eq(FileMeta::getId,fileId)
                        .set(FileMeta::getIsDelete,0)
                        .set(FileMeta::getParentId,fileFolder.getId());
        fileMetaMapper.update(fileUpdateWrapper);
        return Result.ok(FileSuccessConstant.UPDATE_FILEPATH_SUCCESS,null);
    }
    // 删除共享文件权限
    // 清空文件夹文件
    @Transactional
    @Override
    public Result emptyRecycleBin(String userId) {
        // 查询用户回收站文件
        LambdaUpdateWrapper<FileMeta> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(FileMeta::getUserId,userId)
                .eq(FileMeta::getIsDelete,1);
        List<FileMeta> fileMetas = fileMetaMapper.selectList(wrapper);
        // 删除回收站文件
        for (FileMeta fileMeta:fileMetas){
            // 删除文件表数据
            int delete = fileMetaMapper.deleteById(fileMeta.getId());
            if(delete!=1){
                throw new BaseException(ExceptionEnums.SYSTEM_ERROR);
            }
            // 更新存储表
            LambdaUpdateWrapper<UserStorage> storageWrapper = new LambdaUpdateWrapper<>();
            storageWrapper.eq(UserStorage::getId,userId)
                    .setSql("used_size = used_size - " + fileMeta.getFileSize());
            userStorageMapper.update(storageWrapper);
            // 删除minio文件
            String fileName = fileMeta.getFileName();
            String extension = fileName.substring(fileName.lastIndexOf("."));
            String objectName = "/"+userId+"/file/"+fileMeta.getId()+extension;
            Boolean minioDelete = minioService.delete(bucket, objectName);
            if(!minioDelete){
                log.error("删除minio文件失败，objectName:{}",objectName);
                throw new BaseException(ExceptionEnums.SYSTEM_ERROR);
            }
            // 删除预览信息
            if (FileExtensionConstant.convertPreview.contains(fileName.substring(fileName.lastIndexOf(".")))){
                // 删除预览信息
                LambdaQueryWrapper<FilePreview> previewWrapper = new LambdaQueryWrapper<>();
                previewWrapper.eq(FilePreview::getInitialFileId,fileMeta.getId());
                List<FilePreview> filePreviews = filePreviewMapper.selectList(previewWrapper);
                for (FilePreview filePreview:filePreviews){
                    objectName = "/"+userId+"/preview/"+filePreview.getPreviewFileName();
                    minioService.delete(bucket,objectName);
                    filePreviewMapper.deleteById(filePreview.getId());
                }
            }
        }
        return Result.ok(FileSuccessConstant.EMPTY_RECYCLEBIN_SUCCESS,null);
    }
}
